package minesweep.entity;

import minesweep.ServerHandler;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.*;

import static minesweep.constant.ProtocolConstant.*;

/**
 * Created by fuatnow on 17/2/9.
 */
public class Room
{
    private int roomID = -1;
    private Player roomOwer = null;
    private float rate = 0.04f;
    private long createTime;
    private String password = "";
    private boolean isStart = false;
    private ArrayList<Player> membersList = new ArrayList<Player>();
    private GameBoard gameBoard = null;
    private int poolCoinNum = 0;//奖池钱数
    private Timer calc_timer;

    public Room()
    {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                // task to run goes here
               // System.out.println("Hello !!!");
                testCanStartGame();
            }
        };
        Timer timer = new Timer();
        long delay = 0;
        long intevalPeriod = 1000;
        timer.scheduleAtFixedRate(task, delay, intevalPeriod);
    }

    public void addPlayer(Player player)
    {
        boolean hasSamePlayer = false;
        for(int i=0;i<membersList.size();i++)
        {
            if(membersList.get(i).getNetID() == player.getNetID())
            {
                hasSamePlayer = true;
                return;
            }
        }

        player.setRoom(this);
        membersList.add(player);
        player.setEnterTime(System.currentTimeMillis());
        sendRoomReayInfo(WAIT_ROOM);
    }

    public  void sendSomeOnceReady()
    {
        sendRoomReayInfo(READY_ROOM);
        int readyNum = 0;
        for(int i=0;i<membersList.size();i++)
        {
            if(membersList.get(i).isReady())
            {
                readyNum++;
            }
            if(readyNum == 6)
            {
                //游戏开始
                gameStart();
            }
        }
    }

    void sendRoomReayInfo(int cmdID)
    {
        JsonMessage rcpObj = new JsonMessage(cmdID);
        JSONArray infoArray = new JSONArray();
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            infoArray.put(p.getWaitRoomJsonObj());
        }
        rcpObj.put("rolesInfo",infoArray);

        for(int i=0;i<membersList.size();i++)
        {
            JsonMessage jo = new JsonMessage(RCP);
            JSONObject joRoot = jo.getRootObj();
            joRoot.put("netID",membersList.get(i).getNetID());
            joRoot.put("rcpMsg",rcpObj.getRootObj());
            String msg = jo.toString();
            ServerHandler.getMineSweepGateConnection().writeAndFlush(jo.toString());
        }
    }

    void testCanStartGame()
    {
        if(isStart()) return;
        Long curTime = System.currentTimeMillis();
        Long laterEnterTime = 0L;
        int readyPlayerNum = 0;
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            laterEnterTime = Math.max(laterEnterTime,p.getEnterTime());
            if(p.isReady())
            {
                readyPlayerNum++;
            }
        }
        Long disTime = curTime - readyPlayerNum;
        //如果已经有3人准备 并且5秒内没有加入人
        if(readyPlayerNum > 2 && disTime > 5000)
        {
            gameStart();
        }
        else
        {
            for(int i=0;i<membersList.size();i++) {
                Player p = membersList.get(i);
                //如果进入了房间10秒内还没有准备就t掉他
                if(p.isReady() == false && curTime - p.getEnterTime() > 10000)
                {
                    kickPlayer(p,KICKED_BY_OVERTIME,"system");
                }
            }
        }
    }



    void gameStart()
    {
        isStart = true;
        gameBoard = new GameBoard();
        sendGameStart();
    }

    void sendGameStart()
    {
        JsonMessage rcpObj = new JsonMessage(GAME_START);
        JSONArray infoArray = new JSONArray();
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            if(p.isReady())
            {
                infoArray.put(p.getGameStartStateJsonObj());
            }
        }
        rcpObj.put("rolesInfo",infoArray);
        rcpObj.put("boardInfo",gameBoard.getBoardJsonArry());
        rcpObj.put("minesNum",gameBoard.getRemainMinesNum());
        for(int i=0;i<membersList.size();i++)
        {
            JsonMessage jo = new JsonMessage(RCP);
            JSONObject joRoot = jo.getRootObj();
            joRoot.put("netID",membersList.get(i).getNetID());
            joRoot.put("rcpMsg",rcpObj.getRootObj());
            String msg = jo.toString();
            ServerHandler.getMineSweepGateConnection().writeAndFlush(jo.toString());
        }
    }

    public void kickPlayer(Player p,int reason,String byUsrName)
    {
        JsonMessage rcpObj = new JsonMessage(KICK_PLAYER);
        rcpObj.put("kickedUsrID",p.getUsrID());
        rcpObj.put("kickedUsrName",p.getUsrName());
        rcpObj.put("reason",reason);
        rcpObj.put("byUsrName",byUsrName);

        JSONArray infoArray = new JSONArray();
        for(int i=0;i<membersList.size();i++)
        {
            if(p.getUsrID() != membersList.get(i).getUsrID() )
            {
                infoArray.put(p.getWaitRoomJsonObj());
            }
        }

        for(int i=0;i<membersList.size();i++)
        {
            int cmd = BACK_HALL;
            if(p.getUsrID() != membersList.get(i).getUsrID())
            {
                cmd = RCP;
                rcpObj.put("rolesInfo",infoArray);
            }
            else
            {
                rcpObj.getDataObj().remove("rolesInfo");
            }

            JsonMessage jo = new JsonMessage(cmd);
            JSONObject joRoot = jo.getRootObj();
            joRoot.put("netID",membersList.get(i).getNetID());
            joRoot.put("rcpMsg",rcpObj.getRootObj());
            String msg = jo.toString();
            ServerHandler.getMineSweepGateConnection().writeAndFlush(jo.toString());
        }
        membersList.remove(p);
    }

    public void  sendPlayerSelGird(Player p,int row,int col,boolean isMarkMine)
    {
        p.setSelInfo(new SelInfo(row,col,isMarkMine));
        p.setStatus(Player.STU_HAVESEL);
        JSONObject selPlayerInfo = p.getGameSelStateJsonObj();
        JsonMessage rcpObj = new JsonMessage(SELECT_GIRD);
        rcpObj.put("selPlayerInfo",selPlayerInfo);
        int haveSelPlayerNum = 0;
        for(int i=0;i<membersList.size();i++)
        {
            JsonMessage jo = new JsonMessage(RCP);
            JSONObject joRoot = jo.getRootObj();
            joRoot.put("netID",membersList.get(i).getNetID());
            joRoot.put("rcpMsg",rcpObj.getRootObj());
            String msg = jo.toString();
            ServerHandler.getMineSweepGateConnection().writeAndFlush(jo.toString());
            if(membersList.get(i).getStatus() == Player.STU_HAVESEL)
            {
                haveSelPlayerNum++;
            }
        }

        if(haveSelPlayerNum == this.membersList.size())
        {
            TimerTask task = new TimerTask() {
                @Override
                public void run()
                {
                    scoreSettlement();
                    calc_timer.cancel();
                }
            };
            calc_timer = new Timer();
            long delay = 1000;
            calc_timer.schedule(task,delay, delay);
        }
    }

    void scoreSettlement()
    {
        Map<Integer,Integer> girdPlayerMap = new HashMap<Integer,Integer>();
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            int row = p.getSelInfo().row;
            int col = p.getSelInfo().col;
            boolean isMarkMine = p.getSelInfo().isMarkMine;
            Integer key = row*100 + col*10 + (isMarkMine ?  0 : 1);
            boolean hasKey = girdPlayerMap.containsKey(key);
            Integer val = 0;
            if(hasKey == false)
            {
                val = 1;
            }
            else
            {
                val = girdPlayerMap.get(key)+1;
            }
            girdPlayerMap.put(key,val);
        }

        JsonMessage rcpObj = new JsonMessage(CALC_SCORE);
        JSONArray infoArray = new JSONArray();
        rcpObj.put("rolesInfo",infoArray);
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            int row = p.getSelInfo().row;
            int col = p.getSelInfo().col;
            boolean isMarkMine = p.getSelInfo().isMarkMine;
            Integer key = row*100 + col*10 + (isMarkMine ?  0 : 1);
            Integer pNum = girdPlayerMap.get(key);
            boolean isMine = this.gameBoard.isMine(row,col);
            float curScore = p.getScore();
            float addScore = 0;
            int deductCoinNum = 0;
            if(isMine == isMarkMine)
            {
                addScore = 6.0F / pNum;
            }
            else
            {
                deductCoinNum = 5;
                poolCoinNum += 5;
            }
            p.setScore(curScore+addScore);
            this.gameBoard.touchGird(row,col);
            infoArray.put(p.getCalsScoreStateJsonObj(deductCoinNum,addScore));
        }
        rcpObj.put("poolCoin",poolCoinNum);
        rcpObj.put("minesNum",this.gameBoard.getRemainMinesNum());
        rcpObj.put("boardInfo",this.gameBoard.getBoardJsonArry());

        for(int i=0;i<membersList.size();i++)
        {
            JsonMessage jo = new JsonMessage(RCP);
            JSONObject joRoot = jo.getRootObj();
            joRoot.put("netID",membersList.get(i).getNetID());
            joRoot.put("rcpMsg",rcpObj.getRootObj());
            String msg = jo.toString();
            ServerHandler.getMineSweepGateConnection().writeAndFlush(jo.toString());
        }
        for(int i=0;i<membersList.size();i++)
        {
            Player temp = membersList.get(i);
            temp.setStatus(Player.STU_NOSEL);
        }

        if(this.gameBoard.getRemainMinesNum() == 0)
        {
            sendGameOver();
        }
    }

    public void sendGameOver()
    {
        JsonMessage rcpObj = new JsonMessage(GAME_OVER);
        JSONArray infoArray = new JSONArray();
        rcpObj.put("rolesInfo",infoArray);
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            p.setReady(false);
            p.setStatus(Player.STU_NOSEL);
            p.setScore(0);
            p.setEnterTime(System.currentTimeMillis());
            JSONObject jo = new JSONObject();
            jo.put("usrID",p.getUsrID());
            jo.put("headUrl",p.getHeadUrl());
            jo.put("score",p.getScore());
            jo.put("isReady",false);
            infoArray.put(jo);
        }

        for(int i=0;i<membersList.size();i++)
        {
            JsonMessage jo = new JsonMessage(RCP);
            JSONObject joRoot = jo.getRootObj();
            joRoot.put("netID",membersList.get(i).getNetID());
            joRoot.put("rcpMsg",rcpObj.getRootObj());
            String msg = jo.toString();
            ServerHandler.getMineSweepGateConnection().writeAndFlush(jo.toString());
        }

        this.setStart(false);
        poolCoinNum = 0;
    }


    public Player getPlayer(int netID)
    {
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            if(p.getNetID() == netID)
            {
                return p;
            }
        }
        return null;
    }

    public Player getPlayerByUsrID(int usrID)
    {
        for(int i=0;i<membersList.size();i++)
        {
            Player p = membersList.get(i);
            if(p.getUsrID() == usrID)
            {
                return p;
            }
        }
        return null;
    }

    public int getRoomID() {
        return roomID;
    }

    public void setRoomID(int roomID) {
        this.roomID = roomID;
    }

    public Player getRoomOwer() {
        return roomOwer;
    }

    public void setRoomOwer(Player roomOwer) {
        this.roomOwer = roomOwer;
    }

    public float getRate() {
        return rate;
    }

    public void setRate(float rate) {
        this.rate = rate;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isStart() {
        return isStart;
    }

    public void setStart(boolean start) {
        isStart = start;
    }

    public ArrayList<Player> getMembersList() {
        return membersList;
    }

    public void setMembersList(ArrayList<Player> membersList) {
        this.membersList = membersList;
    }

    public GameBoard getGameBoard() {
        return gameBoard;
    }

    public void setGameBoard(GameBoard gameBoard) {
        this.gameBoard = gameBoard;
    }

    public long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(long createTime) {
        this.createTime = createTime;
    }
}
